﻿using System.Collections.Generic;
using System.Diagnostics;
using UIShell.MessageBusService;
using UIShell.OSGi;
using System.Linq;

namespace Pasys.PresentationCore.Impl
{
    //internal class MessageKey
    //{
    //    public bool SubscribeAll { get; set; }
    //    public string CommandName { get; set; }

    //    public override int GetHashCode()
    //    {
    //        var s = string.Format("{0}{1}", SubscribeAll, CommandName);
    //        return s.GetHashCode();
    //    }
    //    public override bool Equals(object obj)
    //    {
    //        var obj2 = obj as MessageKey;
    //        if (obj2 == null)
    //            return false;

    //        return obj2.CommandName.Equals(this.CommandName) && obj2.SubscribeAll.Equals(this.SubscribeAll);
    //    }
    //}

    internal class HandlerContainer<T> where T : CommandContact, new()
    {
        private readonly Dictionary<string, List<MessageBusHandler>> _handlers =
            new Dictionary<string, List<MessageBusHandler>>();

        public HandlerContainer(IMessageBusService messageBusService)
        {
            Debug.Assert(messageBusService != null);
            messageBusService.Subscribe<T>(OnCommandFired);
        }

        private void OnCommandFired(object sender, object args)
        {
            var contact = (T) args;
            List<MessageBusHandler> handlerList;
            if (!_handlers.TryGetValue(contact.CommandName, out handlerList))
            {
                return;
            }
            handlerList.ForEach(handler => handler(contact.Sender, contact));
        }

        public void SubscribeCommandEvent(string commandName, MessageBusHandler handler)
        {
            List<MessageBusHandler> handlerList;
            if (!_handlers.TryGetValue(commandName, out handlerList))
            {
                _handlers[commandName] = handlerList = new List<MessageBusHandler>();
            }
            handlerList.Add(handler);
        }
    }

    public class CommandBusService : ICommandBusService
    {
        private readonly HandlerContainer<CommandContact> _commandContainer;
        private readonly HandlerContainer<CommandStatusContact> _commandStatusContainer;
        private readonly HandlerContainer<ControlStatusContact> _toolbarStatusContainer;
        private readonly HandlerContainer<CommandStatusContact> _commandGroupStatusContainer;


        private readonly IMessageBusService _messageBusService;

        public CommandBusService(IMessageBusService messageBusService)
        {
            Debug.Assert(messageBusService != null);
            _messageBusService = messageBusService;
            _commandContainer = new HandlerContainer<CommandContact>(messageBusService);
            _commandStatusContainer = new HandlerContainer<CommandStatusContact>(messageBusService);
            _toolbarStatusContainer = new HandlerContainer<ControlStatusContact>(messageBusService);

            _commandGroupStatusContainer = new HandlerContainer<CommandStatusContact>(messageBusService);
        }

        private  IShellLayoutViewProxy getProxy()
        {
            IShellLayoutViewProxy shellLayoutView=null;
            var con = BundleRuntime.Instance.GetFirstOrDefaultService<ILayoutViewProxyContainer>();
            if (con != null)
            {
                shellLayoutView = con.LayoutViewProxy;
            }
            if (shellLayoutView == null)
            {
                shellLayoutView = BundleRuntime.Instance.GetFirstOrDefaultService<IShellLayoutViewProxy>();
            }
            return shellLayoutView;
        }
        #region ICommandBusService Members

        public void PublicCommand( string commandName)
        {
            var shellLayoutView=getProxy();
            PublicCommand(shellLayoutView, commandName);
        }
        public void PublicCommand(IFindOwnerForm sender, string commandName)
        {
            _messageBusService.Publish(new CommandContact {Sender=sender, CommandName = commandName});
        }

        public void SubscribeCommandEvent(string commandName, MessageBusHandler handler)
        {
            _commandContainer.SubscribeCommandEvent(commandName, handler);
        }

        public void PublicCommandStatus( string commandName, CommandStatus status)
        {
            var shellLayoutView = getProxy();
            PublicCommandStatus(shellLayoutView, commandName, status);
        }

        public void PublicCommandStatus(IFindOwnerForm sender, string commandName, CommandStatus status)
        {
            _messageBusService.Publish(new CommandStatusContact { Sender = sender, CommandName = commandName, Status = status });
        }

        public void SubscribeCommandStatusEvent(string commandName, MessageBusHandler handler)
        {
            _commandStatusContainer.SubscribeCommandEvent(commandName, handler);
        }

        public void PublicToolbarStatus(string commandName, CommandStatus status)
        {
            var shellLayoutView = getProxy();
            PublicToolbarStatus(shellLayoutView, commandName, status);
        }
        
        public void PublicToolbarStatus(IFindOwnerForm sender, string commandName, CommandStatus status)
        {
            _messageBusService.Publish(new ControlStatusContact { Sender = sender, CommandName = commandName, Status = status });
        }

        public void SubscribeToolbarStatusEvent(string commandName, MessageBusHandler handler)
        {
            _toolbarStatusContainer.SubscribeCommandEvent(commandName, handler);
        }


        //=======================

        public void PublicCommandGroupStatus(string commandGroupName, CommandStatus status)
        {
            var shellLayoutView = getProxy();
            PublicCommandStatus(shellLayoutView, commandGroupName, status);
        }

        public void PublicCommandGroupStatus(IFindOwnerForm sender, string commandGroupName, CommandStatus status)
        {
            _messageBusService.Publish(new CommandStatusContact { Sender = sender, CommandName = commandGroupName, Status = status });
        }

        public void SubscribeCommandGroupStatusEvent(string commandGroupName, MessageBusHandler handler)
        {
            _commandStatusContainer.SubscribeCommandEvent(commandGroupName, handler);
        }


        #endregion
    }
}